# coding: utf-8
import os
import time
import logging
from hashlib import sha1
from flask import request
from xml.etree import ElementTree as etree

from leancloud import Object, Query, errors
from dbModels import WechatKfOLRecord, WechatKfSwitch, AgmKf, WechatShopOrder, AgmStaffUser

TOKEN = 'imfunimfun'

TEXTXML = '''<xml>
<ToUserName><![CDATA[%(touser)s]]></ToUserName>
<FromUserName><![CDATA[%(fromuser)s]]></FromUserName>
<CreateTime>%(createtime)s</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[%(content)s]]></Content>
</xml>'''

KFXML = '''<xml>
    <ToUserName><![CDATA[%(touser)s]]></ToUserName>
    <FromUserName><![CDATA[%(fromuser)s]]></FromUserName>
    <CreateTime>%(createtime)s</CreateTime>
    <MsgType><![CDATA[transfer_customer_service]]></MsgType>
</xml>'''

CACHE_WECHAT_WELCOME_ID = '563d5ad060b25749ea123f6a'

def get():
    sign = request.args.get('signature')
    timestamp = request.args.get('timestamp')
    nonce = request.args.get('nonce')
    echostr = request.args.get('echostr')
    
    if (sign and timestamp and nonce and echostr and 
        checksign(sign, timestamp, nonce, TOKEN)):
        return echostr
    return 'WeChatGET'
    
def post():
    if request.data and request.content_type == 'text/xml':
        xml = etree.XML(request.data)
        if not os.environ.get('VIRTUAL_ENV', '').startswith('F:'): #判断是否本地
            log_wechat(xml)
        msgtype = xml.find('MsgType')  # 判断类型
        if msgtype is not None and msgtype.text == 'text': #类型为消息
            # if xml.find('Content').text == u'取消客服模式':
                # return cancelKfMode(xml)
            # if checkKfSwitch(xml):
                # return replyKfMode(xml)
            if xml.find('Content').text == u'申请销售':
                from tools.wechatAPI import replyNews 
                cacheid = '56c81d35a341310054e463c0'
                content = Query(Object.extend('Cache_list')).get(cacheid).get('content')
                return replyNews(xml, content)
            if xml.find('Content').text == u'申请音速风暴客服':
                return replyApplyKf(xml)
            if xml.find('Content').text.startswith(u'英宝玩具公司#'):
                return replyTextMessage(signAgmStaff(xml), xml)
            if xml.find('Content').text == u'测试自动回复':
                from tools.wechatReply import replyAutoResponderTip
                return replyAutoResponderTip(xml)            
            appkeywords = ['APP', 'app', 'App', '下载APP']
            if xml.find('Content').text in appkeywords:
                content = '<a href="https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx147a7583c9622a1b&redirect_uri=http%3A//m.top-racer.com/auth%3Fgoto%3Ddownapp&response_type=code&scope=snsapi_base#wechat_redirect">App下载</a>'
                return replyTextMessage(content, xml)
            #kfkeywords = [u'客服', u'你好', u'您好', u'在吗']
            #for t in kfkeywords:
                #if t in xml.find('Content').text:
                    #return replytoKf(xml)
            jmkeywords = [u'加盟', u'代理', u'合作', u'销售']
            for t in jmkeywords:
                if t in xml.find('Content').text:
                    content = u'相关商务合作，麻烦您加QQ:2262985089, 或者电话 15815007567\n工作时间：\n周一到周五及周日 8:30-11:30，13:30-17:30, 18:30-21:30'
                    return replyTextMessage(content, xml)
            videoskeywords = [u'安装视频', u'指导视频', u'教学视频']
            for t in videoskeywords:
                if t in xml.find('Content').text:
                    from tools.wechatReply import replyInstructVideo
                    return replyInstructVideo(xml)
            smkeywords = [u'说明书', u'怎样安装',u'如何安装', u'安装方法',u'怎么安装']
            for t in smkeywords:
                if t in xml.find('Content').text:
                    from tools.wechatReply import replyInstruct
                    return replyInstruct(xml)
            # wtkeywords = [u'拼装不了', u'车子不跑', u'电源', u'控制器', u'遥控器', u'装不上']
            # for t in wtkeywords:
                # if t in xml.find('Content').text:
                    # content = u'请点击 “会员服务--人工服务”或者拨打400电话 4008-950-350\n400电话工作时间：\n周一到周五及周日 8:30-11:30，13:30-17:30, 18:30-21:30'
                    # return replyTextMessage(content, xml)
            pjkfkeywords = ['1', '2', '3', '4', '5']
            if xml.find('Content').text in pjkfkeywords:
                content = pjkf(xml, xml.find('Content').text)
                if content:
                    return content
            autoreplykeywords = ['01', '02', '199', '198','197', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '201', '202', '203', '204', '205', '206', '207', '208']
            if xml.find('Content').text in autoreplykeywords:
                from tools.wechatReply import replyAutoResponder
                content = replyAutoResponder(xml)
                return content or 'success'
            if xml.find('Content').text == '013':
                return replytoKf(xml)
            if u'积分' in xml.find('Content').text:
                content = checkjf(xml)
                return replyTextMessage(content, xml)
            if u'新品' in xml.find('Content').text:
                from tools.wechatAPI import replyNews
                return replyNews(xml)
            if xml.find('Content').text.startswith('@'):
                from agmsell import sendqrtowechat
                text = xml.find('Content').text
                openid = xml.find('FromUserName').text
                content = sendqrtowechat(text, openid)
                if content:
                    return replyTextMessage(content, xml)
            from tools.wechatReply import replyAutoResponderTip
            return replyAutoResponderTip(xml)            
            #replytokfwx(xml)        
            #return replyKfMode(xml)
        if msgtype is not None and msgtype.text in ['voice', 'image', 'shortvideo']:
            return replyKfMode(xml)
            # if u'客服' in xml.find('Content').text:
                # return replytoKf(xml)
            # content = 'Test,Ahaha\xe2\x98\x80'
            # return replyTextMessage(content, xml)
        if msgtype is not None and msgtype.text == 'location':  #上传位置时
            from agmbeta import getshopstowechat
            from tools.wechatAPI import replyNews
            items = getshopstowechat(xml)
            if items:
                return replyNews(xml, items)
            loc_x = xml.find('Location_X').text
            loc_y = xml.find('Location_Y').text
            scale = xml.find('Scale').text
            label = xml.find('Label').text
            content = (u'本次地理信息:\nloc_x:%s\nloc-y:%s\nscale:%s\nlabel:%s' % 
                (loc_x, loc_y, scale, label))
            return replyTextMessage(content, xml)
        if msgtype is not None and msgtype.text == 'event': #类型为事件
            event = xml.find('Event')
            if event is not None and event.text == 'subscribe': #事件为关注 
                if xml.find('EventKey') is not None and xml.find('EventKey').text and 'qrscene_' in xml.find('EventKey').text:
                    do_subscribe(xml)
                    result = replyTextMessage(doqrcode(xml), xml)
                else:
                    result = do_subscribe(xml)
                #此处关注时同时增加新品发布的消息发送
                from tools.wechatAPI import sendmessage, WECHATNEWITEMS_ID
                subscribeid = WECHATNEWITEMS_ID
                subscribeid = '56b937c8c24aa80054827b25'
                openid = xml.find('FromUserName').text
                newitems = Query(Object.extend('Cache_list')).get(subscribeid).get('content')
                sendmessage(openid, newitems, 'news')
                return result
            if event is not None and event.text == 'unsubscribe': #事件为取消关注
                do_unsubscribe(xml)
            if event is not None and event.text == 'SCAN': #事件为扫描二维码
                content = doqrcode(xml)
                # content = 'You QrCode SceneValue is %s' % xml.find('EventKey').text
                return replyTextMessage(content, xml)
            if event is not None and event.text == 'CLICK': #事件为自定义菜单点击
                if xml.find('EventKey').text == 'contactkf': #自定义值contactkf
                    return replytoKf(xml)
                if xml.find('EventKey').text == 'xpfb':
                    from tools.wechatAPI import replyNews
                    return replyNews(xml)
                if xml.find('EventKey').text == 'lgwh':
                    from tools.wechatAPI import replyNews
                    cacheid = '56721dc260b259ca8af55b20'
                    content = Query(Object.extend('Cache_list')).get(cacheid).get('content')
                    return replyNews(xml, content)
                if xml.find('EventKey').text == 'xpfben':
                    from tools.wechatAPI import replyNews
                    cacheid = '56e7d0cdefa63100543d2ad0'
                    content = Query(Object.extend('Cache_list')).get(cacheid).get('content')
                    return replyNews(xml, content)
                if xml.find('EventKey').text == 'lgwhen':
                    from tools.wechatAPI import replyNews
                    cacheid = '56e7d0a8731956005c057fc4'
                    content = Query(Object.extend('Cache_list')).get(cacheid).get('content')
                    return replyNews(xml, content)
                if xml.find('EventKey').text in ['hdzxen', 'bszxen']:
                    content = 'Sorry, this function is in development'
                    return replyNews(xml, content)
                content = u'抱歉, 当前功能正在开发中...'
                return replyTextMessage(content, xml)
            if event is not None and event.text == 'kf_create_session': #事件为建立客服会话
                from tools.wechatAPI import getkfsdict
                kfaccount = xml.find('KfAccount').text
                try:
                    kfid = getkfsdict()[kfaccount]['kf_nick']
                except KeyError:
                    kfid = getkfsdict(True)[kfaccount]['kf_nick']
                content = u'您已经进入客服对话模式,客服(%s)为您服务' % kfid
                sendmessage2(xml, content)
            if event is not None and event.text == 'kf_close_session': #事件为退出客服会话
                if xml.find('CloseType') is not None and xml.find('CloseType') in ['TIMEOUT', 'LOGOUT']:
                    return 'success'
                from tools.wechatAPI import getkfsdict
                kfaccount = xml.find('KfAccount').text
                kfid = getkfsdict()[kfaccount]['kf_nick']                
                content = u'您已退出客服对话模式, 结束与客服(%s)的对话\n您可以在十分钟内对本次服务进行评价,回复1-5数字:\n1非常满意\n2比较满意\n3一般\n4不满意\n5非常不满意' % kfid
                sendmessage2(xml, content)         
            if event is not None and event.text == 'merchant_order': #事件为微信小店订单
                doshoporder(xml)
        return 'success'

    return 'WeChatPost'
    
def checksign(sign, timestamp, nonce, token):
    l = [timestamp, nonce, token]
    l.sort()
    s = ''.join(l)
    return sha1(s).hexdigest() == sign
    
def log_wechat(xml):
    msgtype = xml.find('MsgType')
    if msgtype is not None and msgtype.text == 'event':
        objectName = 'Log_Wechat_Event'
    else:
        objectName = 'Log_Wechat_Message'        
    log  = Object.extend(objectName)()
    convertDict = {
        'CreateTime': int, 
        'Location_X': float, 'Location_Y': float, 'Scale': int,
        'Latitude': float, 'Longitude': float, 'Precision': float,
        }
    tostringKeys = {'ScanCodeInfo', 'SendPicsInfo', 'SendLocationInfo'}
    for t in xml:
        name, value = t.tag, t.text
        if name in convertDict:
            try:
                value = convertDict[name](value)
            except ValueError:
                pass
        elif name in tostringKeys:
            value = etree.tostring(t)
        log.set(name, value)
    try:
        log.save()
    except:
        Object.extend('WechatErrorLog')(content=etree.tostring(xml)).save()
    
def do_subscribe(xml):
    rev_openid = xml.find('FromUserName').text
    from tools.wechatAPI import get_save_userinfo_api, movetogroup
    user = get_save_userinfo_api(rev_openid)
    try:
        content = Query(Object.extend('Cache')).get(CACHE_WECHAT_WELCOME_ID).get('content')
        try:
            content = content % (user.get('nickname') or u'朋友')
        except TypeError:
            pass
    except errors.LeanCloudError:
        content = 'Welcome to Top-Race!\xe2\x98\x80'
    if user.get('role') == 'agmsell':
        movetogroup(rev_openid, 102)
    elif user.get('role') == 'agmstaff':
        movetogroup(rev_openid, 104)
    return replyTextMessage(content, xml)

def do_unsubscribe(xml):
    rev_openid = xml.find('FromUserName').text
    query = Query(Object.extend('WechatUser'))
    query.equal_to('openid', rev_openid)
    try:
        user = query.first()
        user.set('subscribe', 0)
        user.save()
    except errors.LeanCloudError:
        pass
        
    
def replyTextMessage(content, xml):
    send_var = rev_xml_to_send_var(xml)
    send_var['content'] = content
    return TEXTXML % send_var
    
def rev_xml_to_send_var(xml):
    rev_data = {}
    var = {}
    for t in xml:
        rev_data[t.tag] = t.text
    var['touser'] = rev_data['FromUserName']
    var['fromuser'] = rev_data['ToUserName']
    var['createtime'] = rev_data['CreateTime']
    
    return var
    
def replytoKf(xml):
    send_var = rev_xml_to_send_var(xml)
    #增加当前客服判断
    from tools.wechatAPI import getkflist, getkfsdict
    for i in xrange(3):
        kfonlinelist = getkflist(True)
        if isinstance(kfonlinelist, list):
            break
        else:
            import logging
            logging.error('(%s)TryingGetKfonlinelistError:%s' % (i, kfonlinelist))
    if not isinstance(kfonlinelist, list):
        # send_var['content'] = '%s' % kfonlinelist
        print 'kfonlinelistError:%s' % kfonlinelist
        logging.error('kfonlinelistError:%s' % kfonlinelist)
        send_var['content'] = u'系统繁忙,请稍候重试'
        return TEXTXML % send_var
    kfsdict = getkfsdict()
    kfidsol = []
    for t in kfonlinelist:
        try:
            kfid = kfsdict[t['kf_account']]['kf_nick']
        except KeyError:
            kfsdict = getkfsdict(True)
            kfid = kfsdict[t['kf_account']]['kf_nick']
        kfidsol.append(kfid)
    print kfonlinelist
    if kfonlinelist:         
        # content = u'正在为您接入客服,请稍等!'
        content = u'当前在线客服: %s\n请耐心等待客服接入' % ', '.join(kfidsol)
        try:
            sendmessage2(xml, content)
            # saveKfOLRecord(xml, kfidsol)
        except:
            import logging, traceback
            logging.error(traceback.format_exc())            
    else:
        # try:
            # saveKfOLRecord(xml, [])
        # except:
            # import logging, traceback
            # logging.error(traceback.format_exc())        
        # sendmessage2(xml, content)
        # replytokfwx(xml)
        #content = u'抱歉, 当前没有客服在线,请其它时间再尝试\n或者拨打400电话 4008-950-350\n400电话工作时间：\n周一到周五及周日 8:30-11:30，13:30-17:30, 18:30-21:30\n直接留言,客服会在下次接入时看到您的留言信息。'
        content = u'抱歉, 当前没有客服在线,请其它时间再尝试\n或者拨打400电话 4008-950-350\n值班时间:周一至周日  8：00-11：30  13：30-17：30'
        #content = u'亲爱的顾客朋友，我公司春节放假时间为2月10日（廿五），开工时间为2月27日（十二）。在此期间，客服人员将会以不定时值班形式在线解答您的问题。因放假带来的不便敬请谅解，并祝您度过一个幸福快乐的新春佳节。'
        sendmessage2(xml, content)
    replytokfwx(xml)    
    return KFXML % send_var
    
def sendmessage2(xml, content):
    openid = xml.find('FromUserName').text
    from tools.wechatAPI import sendmessage
    sendmessage(openid, content)

def doqrcode(xml):
    qrcode = xml.find('EventKey').text
    if 'qrscene_' in qrcode:
        qrcode = qrcode.split('qrscene_')[-1]
    openid = xml.find('FromUserName').text
    if qrcode == 'signAgmStaff':
        content = u'欢迎注册成为英宝玩具员工，请回复[英宝玩具公司#您所在部门#您的姓名](不包括方括号)内容后完成注册操作！'
        return content
    from agmsell import validqrcode
    return validqrcode(qrcode, openid)
    
def checkjf(xml):
    openid = xml.find('FromUserName').text
    users = Query(Object.extend('WechatUser')).equal_to('openid', openid).find()
    if users:
        jf = users[0].get('jf')
        return u'你的积分为:%s' %jf
    else:
        return 'SomethingError'
        
def saveKfOLRecord(xml, kfidsol):
    openid = xml.find('FromUserName').text
    CreateTime = int(xml.find('CreateTime').text)
    WechatKfOLRecord(openid=openid, kfidsol=kfidsol, CreateTime=CreateTime).save()
    if kfidsol:
        WechatKfSwitch(openid=openid, switch='on').save()
    
def checkKfSwitch(xml):
    openid = xml.find('FromUserName').text
    query = Query(WechatKfSwitch)
    query.equal_to('openid', openid)
    from datetime import datetime, timedelta
    query.greater_than('createdAt', datetime.now()-timedelta(hours=48))
    query.descending('updatedAt')
    ret = query.limit(1).find()
    if not ret:
        return False
    if ret[0].get('switch') != 'on':
        return False
    return True

def replyKfMode(xml):
    content = u'您当前已处于客服模式状态下\n(所有消息内容都会保留到客服系统中(48小时)，客服在线接入时会直接看到。如果本模式影响到您在本公众号的其它服务，请直接回复“取消客服模式”恢复正常模式)'
    # sendmessage2(xml, content)    
    return KFXML % rev_xml_to_send_var(xml)

def cancelKfMode(xml):
    openid = xml.find('FromUserName').text
    query = Query(WechatKfSwitch).equal_to('openid', openid).descending('updatedAt')
    ret = query.limit(1).find()
    if ret:
        ret = ret[0]
        ret.set('switch', 'off')
        ret.save()
    content = u'您已成功取消客服模式，消息不再保留于客服系统中。'
    return replyTextMessage(content, xml)
    
        
def pjkf(xml, num):
    openid = xml.find('FromUserName').text
    expire = 10*60 # 1 minute
    now = time.time()
    query = Query(Object.extend('Log_Wechat_Event'))
    query.equal_to('Event', 'kf_close_session')
    query.equal_to('FromUserName', openid)
    query.greater_than('CreateTime', now-expire)
    query.descending('CreateTime')
    kf_close = query.find()
    if kf_close:
        kf_close = kf_close[0]
        kf = kf_close.get('KfAccount')
        closetime = kf_close.get('CreateTime')
        if Query(Object.extend('WechatKfPj')).equal_to('eventid', kf_close.id).find():
            content = '您已经对本次客服对话进行过评价,请不要重复操作,感谢您的参与和支持'
            return replyTextMessage(content, xml)
        Object.extend('WechatKfPj')(openid=openid, pj=int(num), kf=kf, closetime=closetime, eventid=kf_close.id).save()
        content = '感谢您的评价，我们将不断改进我们的服务质量，再次感谢您的参与和支持'
        return replyTextMessage(content, xml)
    # else:
        # content = '无效关键字或超时'
        # return replyTextMessage(content, xml)
        
def replyApplyKf(xml):
    openid = xml.find('FromUserName').text
    if Query(AgmKf).equal_to('openid', openid).find():
        return replyTextMessage(u'请勿重复申请客服', xml)
    query = Query(Object.extend('WechatUser')).equal_to('openid', openid)
    wechatuser = query.find()
    if wechatuser:
        wechatuser = wechatuser[0]
        AgmKf(openid=openid, 
            nickname=wechatuser.get('nickname_emoji') or wechatuser.get('nickname'),
            headimgurl=wechatuser.get('headimgurl'),
            accept=0
        ).save()
        return replyTextMessage(u'已成功申请客服，等待管理员审核', xml)
        
def replytokfwx(xml):
    openid = xml.find('FromUserName').text
    user = getwechatuser(openid)
    nickname = user.get('nickname_emoji') or user.get('nickname')
    msgtype = xml.find('MsgType')
    is_msg = True
    if msgtype is not None and msgtype.text == 'event':
        content = u'用户(%s)点击人工服务菜单' % nickname
        is_msg = False
    else:
        content = u'(客服转发)\n' + nickname + ':'
        content += xml.find('Content').text
    content += u'\n<a href="http://m.top-racer.com/kfchat?uid=%s">查看详情</a>' % user.id
    kfs = Query(AgmKf).equal_to('accept', 1).find()
    from tools.wechatAPI import sendmessage, sendableUserOpenids, send_kf_message
    now = int(time.time())
    for kf in kfs:
        openid = kf.get('openid')
        sendable = False and sendableUserOpenids(openid=openid)#取消
        if sendable:
            sendmessage(kf.get('openid'), content+timeToLimitText(sendable, now))
        elif is_msg:
            send_kf_message(openid, nickname, xml.find('Content').text, "http://m.top-racer.com/kfchat?uid=%s" % user.id)
        else:
            content = u'用户(%s)点击人工服务菜单' % nickname
            send_kf_message(openid, nickname, content, "http://m.top-racer.com/kfchat?uid=%s" % user.id)
            


    
def timeToLimitText(ctime, now=None):
    limit = 60*60*48  # 48 hours
    if not now:
        now = int(time.time())
    remain = limit - (now - ctime)
    hour = remain/3600
    min = remain%3600/60
    sec = remain%60
    return u'\n[%s小时%s分钟%s秒后 无法接收]' % (hour, min, sec)    
    
def getwechatuser(openid):
    wechatuser = Query(Object.extend('WechatUser')).equal_to('openid', openid).find()
    if wechatuser:
        return wechatuser[0]
    from tools.wechatAPI import get_save_userinfo_api
    return get_save_userinfo_api(openid)
    
def doshoporder(xml):
    openid = xml.find('FromUserName').text
    oid = xml.find('OrderId').text
    from tools.wechatAPI import get_order_detail, send_shop_order, send_order_confirm
    order = get_order_detail(oid)['order']
    saveLogDict(WechatShopOrder(), order)
    send_order_confirm(openid, oid, order)
    senders = Query(Object.extend('Cache_list')).get('584670f7a22b9d007aa65849').get('content')
    for sender in senders:
        send_shop_order(sender, oid, order)
    
    
def saveLogDict(log, d):
    for k in d:
        if d[k]:
            log.set(k, d[k])
    log.save()

def signAgmStaff(xml):
    openid = xml.find('FromUserName').text
    text = xml.find('Content').text
    data = text.split('#')
    if len(data) != 3:
        return u"数据输入有误"
    depart = data[1]
    name = data[2]
    user = Query(AgmStaffUser).equal_to('openid', openid).find()
    if user:
        from tools.wechatAPI import movetogroup
        movetogroup(openid, 104)    
        return u"该微信号已经绑定员工信息，请勿重复注册"
    user = AgmStaffUser(openid=openid, depart=depart, name=name)
    user.save()
    user = Query(Object.extend('WechatUser')).equal_to('openid', openid).find()
    if not user:
        return u'账号异常'
    from tools.wechatAPI import movetogroup
    if not user[0].get('role'):
        user[0].set('role', 'agmstaff').save()
    movetogroup(openid, 104)    
    return u'恭喜您，已注册英宝玩具公司员工成功，请返回微信主界面再重新进入公众号，即可进入微平台-<a href="http://m.top-racer.com/agmstaff">员工天地</a>。'
